package com.abel.bigwater.dataserver.model.qdies

import com.abel.bigwater.data.BcdString
import com.abel.bigwater.dataserver.model.PacketCmdException
import com.abel.bigwater.dataserver.model.PacketDataLenException
import io.netty.buffer.ByteBuf

open class DtenAskAnalogConfigData(_len: Int) : D10BaseData(_len) {
    override var type = FuncType.AskAnalogConfig

    var internalAddr: Byte? = null

    var analogMeter = AnalogMeterType.Pressure

    var rangeHigh: Float? = null
    var rangeLow: Float? = null

    var warnHigh: Float? = null
    var warnLow: Float? = null


    var readMode = ReadModeType.DayMode

    /**
     * 上传时刻 2字节 两个字节分别代表星期， 小时
    的BCD码
     */
    var uploadStart: BcdString? = null

    var samplePeriod: Int? = null

    var uploadPeriod: Short? = null

    var volt: Short? = null

    override fun fill(buf: ByteBuf) {
        assert(internalAddr != null && uploadStart?.size == 2 && samplePeriod != null && uploadPeriod != null)
        buf.apply {
            writeByte(internalAddr!!.toInt())
            writeByte(analogMeter.code)

            writeFloat(rangeHigh!!)
            writeFloat(rangeLow!!)
            writeFloat(warnHigh!!)
            writeFloat(warnLow!!)

            writeByte(readMode.code.toInt())
            writeBytes(uploadStart!!.hexArray)
            writeShort(samplePeriod!!)
            writeByte(uploadPeriod!!.toInt())

            writeByte(volt!!.toInt())
        }
    }

    override fun parse(buf: ByteBuf): Boolean {
        buf.apply {
            if (readableBytes() < MIN_LEN) {
                throw PacketDataLenException("not enough: ${readableBytes()}")
            }
            internalAddr = readByte()
            val m1v = readByte()
            val m1 = AnalogMeterType.values().find { it.code == m1v.toInt() }
                    ?: throw PacketCmdException("invalid analog meter type: $m1v")
            analogMeter = m1

            rangeHigh = readFloat()
            rangeLow = readFloat()
            warnHigh = readFloat()
            warnLow = readFloat()

            val r1 = readByte()
            if (ReadModeType.values().find { it.code == r1 } == null) {
                throw PacketCmdException("invalid read-mode: $r1")
            }
            readMode = ReadModeType.values().find { it.code == r1 }!!

            uploadStart = BcdString.create(this, 2)
            samplePeriod = readUnsignedShort()
            uploadPeriod = readUnsignedByte()

            volt = readUnsignedByte()
        }

        return true
    }

    override fun count(): Int = MIN_LEN

    companion object {
        const val MIN_LEN = 1 + 1 + 4 * 4 + 1 + 2 + 2 + 1 + 1
    }
}

enum class AnalogMeterType(val code: Int) {
    Pressure(1),
    Temperature(2),
    Other(3)
}